# -*- coding: utf-8 -*-
"""
辅助工具函数模块
提供各种通用的辅助函数
"""

import re
import json
import time
import hashlib
from datetime import datetime, timezone
from typing import Any, Dict, List, Optional, Union
from pathlib import Path


def generate_timestamp(format_str: str = "%Y-%m-%d %H:%M:%S") -> str:
    """
    生成当前时间戳
    
    Args:
        format_str: 时间格式字符串
        
    Returns:
        str: 格式化的时间字符串
    """
    return datetime.now().strftime(format_str)


def generate_iso_timestamp() -> str:
    """
    生成ISO格式的时间戳
    
    Returns:
        str: ISO格式时间字符串
    """
    return datetime.now(timezone.utc).isoformat()


def get_timestamp(format_str: str = "%Y-%m-%d %H:%M:%S") -> str:
    """
    获取当前时间戳（generate_timestamp的别名）
    
    Args:
        format_str: 时间格式字符串
        
    Returns:
        str: 格式化的时间字符串
    """
    return generate_timestamp(format_str)


def format_response_time(response_time: float) -> str:
    """
    格式化响应时间
    
    Args:
        response_time: 响应时间（秒）
        
    Returns:
        str: 格式化的响应时间字符串
    """
    if response_time < 0.001:
        return f"{response_time * 1000000:.0f}μs"
    elif response_time < 1:
        return f"{response_time * 1000:.0f}ms"
    else:
        return f"{response_time:.3f}s"


def validate_email(email: str) -> bool:
    """
    验证邮箱格式
    
    Args:
        email: 邮箱地址
        
    Returns:
        bool: 是否为有效邮箱格式
    """
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None


def sanitize_filename(filename: str) -> str:
    """
    清理文件名，移除不安全字符
    
    Args:
        filename: 原始文件名
        
    Returns:
        str: 清理后的文件名
    """
    # 移除或替换不安全字符
    unsafe_chars = r'[<>:"/\\|?*]'
    safe_filename = re.sub(unsafe_chars, '_', filename)
    
    # 移除前后空格和点
    safe_filename = safe_filename.strip(' .')
    
    # 确保文件名不为空
    if not safe_filename:
        safe_filename = 'unnamed_file'
    
    return safe_filename


def deep_merge_dict(dict1: Dict[str, Any], dict2: Dict[str, Any]) -> Dict[str, Any]:
    """
    深度合并两个字典
    
    Args:
        dict1: 第一个字典
        dict2: 第二个字典
        
    Returns:
        Dict[str, Any]: 合并后的字典
    """
    result = dict1.copy()
    
    for key, value in dict2.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = deep_merge_dict(result[key], value)
        else:
            result[key] = value
    
    return result


def generate_hash(data: Union[str, bytes, Dict[str, Any]], algorithm: str = 'md5') -> str:
    """
    生成数据的哈希值
    
    Args:
        data: 要哈希的数据
        algorithm: 哈希算法 (md5, sha1, sha256)
        
    Returns:
        str: 哈希值
    """
    if isinstance(data, dict):
        data = json.dumps(data, sort_keys=True)
    
    if isinstance(data, str):
        data = data.encode('utf-8')
    
    hash_func = getattr(hashlib, algorithm.lower())
    return hash_func(data).hexdigest()


def safe_json_loads(json_str: str, default: Any = None) -> Any:
    """
    安全的JSON解析
    
    Args:
        json_str: JSON字符串
        default: 解析失败时的默认值
        
    Returns:
        Any: 解析结果或默认值
    """
    try:
        return json.loads(json_str)
    except (json.JSONDecodeError, TypeError):
        return default


def safe_json_dumps(data: Any, default: str = '{}') -> str:
    """
    安全的JSON序列化
    
    Args:
        data: 要序列化的数据
        default: 序列化失败时的默认值
        
    Returns:
        str: JSON字符串或默认值
    """
    try:
        return json.dumps(data, ensure_ascii=False, indent=2)
    except (TypeError, ValueError):
        return default


def extract_json_path(data: Dict[str, Any], path: str, default: Any = None) -> Any:
    """
    从JSON数据中提取指定路径的值
    
    Args:
        data: JSON数据
        path: 路径，使用点号分隔 (例: 'user.profile.name')
        default: 路径不存在时的默认值
        
    Returns:
        Any: 提取的值或默认值
    """
    try:
        keys = path.split('.')
        result = data
        
        for key in keys:
            if isinstance(result, dict) and key in result:
                result = result[key]
            elif isinstance(result, list) and key.isdigit():
                index = int(key)
                if 0 <= index < len(result):
                    result = result[index]
                else:
                    return default
            else:
                return default
        
        return result
    except (KeyError, TypeError, ValueError):
        return default


def create_directory(path: Union[str, Path], exist_ok: bool = True) -> Path:
    """
    创建目录
    
    Args:
        path: 目录路径
        exist_ok: 目录已存在时是否报错
        
    Returns:
        Path: 目录路径对象
    """
    path_obj = Path(path)
    path_obj.mkdir(parents=True, exist_ok=exist_ok)
    return path_obj


def read_file(file_path: Union[str, Path], encoding: str = 'utf-8') -> Optional[str]:
    """
    读取文件内容
    
    Args:
        file_path: 文件路径
        encoding: 文件编码
        
    Returns:
        Optional[str]: 文件内容或None
    """
    try:
        with open(file_path, 'r', encoding=encoding) as f:
            return f.read()
    except (FileNotFoundError, IOError, UnicodeDecodeError):
        return None


def write_file(file_path: Union[str, Path], content: str, encoding: str = 'utf-8') -> bool:
    """
    写入文件内容
    
    Args:
        file_path: 文件路径
        content: 文件内容
        encoding: 文件编码
        
    Returns:
        bool: 是否写入成功
    """
    try:
        path_obj = Path(file_path)
        path_obj.parent.mkdir(parents=True, exist_ok=True)
        
        with open(file_path, 'w', encoding=encoding) as f:
            f.write(content)
        return True
    except (IOError, UnicodeEncodeError):
        return False


def measure_execution_time(func):
    """
    测量函数执行时间的装饰器
    
    Args:
        func: 要测量的函数
        
    Returns:
        tuple: (函数返回值, 执行时间)
    """
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        execution_time = end_time - start_time
        return result, execution_time
    return wrapper


def retry_operation(func, max_retries: int = 3, delay: float = 1.0, backoff: float = 2.0):
    """
    重试操作
    
    Args:
        func: 要重试的函数
        max_retries: 最大重试次数
        delay: 初始延迟时间（秒）
        backoff: 延迟时间倍数
        
    Returns:
        Any: 函数执行结果
        
    Raises:
        Exception: 重试次数用尽后的最后一次异常
    """
    last_exception = None
    current_delay = delay
    
    for attempt in range(max_retries + 1):
        try:
            return func()
        except Exception as e:
            last_exception = e
            if attempt < max_retries:
                time.sleep(current_delay)
                current_delay *= backoff
            else:
                raise last_exception


def format_file_size(size_bytes: int) -> str:
    """
    格式化文件大小
    
    Args:
        size_bytes: 文件大小（字节）
        
    Returns:
        str: 格式化的文件大小字符串
    """
    if size_bytes == 0:
        return "0B"
    
    size_names = ["B", "KB", "MB", "GB", "TB"]
    i = 0
    size = float(size_bytes)
    
    while size >= 1024.0 and i < len(size_names) - 1:
        size /= 1024.0
        i += 1
    
    return f"{size:.1f}{size_names[i]}"


def truncate_string(text: str, max_length: int = 100, suffix: str = "...") -> str:
    """
    截断字符串
    
    Args:
        text: 原始字符串
        max_length: 最大长度
        suffix: 截断后缀
        
    Returns:
        str: 截断后的字符串
    """
    if len(text) <= max_length:
        return text
    
    return text[:max_length - len(suffix)] + suffix


def ensure_dir_exists(dir_path: Union[str, Path]) -> Path:
    """
    确保目录存在，如果不存在则创建
    
    Args:
        dir_path: 目录路径
        
    Returns:
        Path: 目录路径对象
    """
    path = Path(dir_path)
    path.mkdir(parents=True, exist_ok=True)
    return path